namespace ImapX
{
    using System;
    using System.Collections;
    using System.Collections.Generic;
    using System.Globalization;
    using System.Text.RegularExpressions;

    public class Folder
    {
        public Imap _client;
        private int _exists;
        private string _folderName;
        private string _folderPath;
        internal bool _hasChildren;
        private int _lastMessageUpdateCount;
        private MessageCollection _messages;
        private int _recents;
        private FolderCollection _subFolders;
        private int _uidNext;
        private string _uidValidity;
        private int _unseen;
        public bool _noselect = false;

        public Folder(string folderName)
        {
            this._folderName = folderName;
            this._subFolders = new FolderCollection();
        }

        public string GetRawMessageData(Message message)
        {
            ArrayList sResultArray = new ArrayList();
            string command = string.Concat("UID FETCH ", message.MessageUid, " BODY.PEEK[]\r\n");
            string result = _client.SendAndReceive(command);

            //TODO:Regex?

            //sResultArray.RemoveAt(0);
            //sResultArray.RemoveRange(sResultArray.Count - 2, 2);

            //string result = String.Join("\r\n", (string[])sResultArray.ToArray(typeof(string)));

            return result;
        }

        //public bool AppendRawMessageData(string messageData)
        //{
        //    // Save the selected folder and select this folder
        //    string folderName = this._client._selectedFolder;
        //    this.Select();

        //    TimeSpan timezoneOffset = TimeZone.CurrentTimeZone.GetUtcOffset(msg.Date);

        //    ArrayList sResultArray = new ArrayList();
        //    string command = string.Concat(new object[] { "APPEND \"", this.FolderPath, "\"", dateParam, " {", messageData.Length - 2, "}\r\n" });
        //    bool result = (this._client.SendAndReceive(command, ref sResultArray) && this._client.SendData(messageData));

        //    // restore the originally selected folder
        //    this._client.SelectFolder(folderName);

        //    return result;
        //}

        public Message AppendMessage(Message msg)
        {
            Message newMessage = null;

            int uid = -1;

            if ((this._client == null) && !this._client._isConnected)
            {
                throw new ImapException("Client Not Connected");
            }
            if (msg == null)
            {
                throw new ImapException("Message is null");
            }

            string folderName = this._client._selectedFolder;
            Select();

            //string data = msg.messageBuilder();
            byte[] data = msg.OriginalData;

            uid = _client.Append(this.FolderPath, msg.OriginalData, msg.Flags.ToString(), msg.InternalDate);

            // add the new message to the collection
            newMessage = new Message(_client, uid, this);
            Messages.Add(newMessage);

            // return to original folder
            _client.SelectFolder(folderName);

            return newMessage;
        }

        public MessageCollection CheckNewMessage(bool processMessages)
        {
            MessageCollection messages = new MessageCollection();
            MessageCollection messages2 = new MessageCollection();
            messages2 = this._client.SearchMessage("all", this);
            int result = -1;
            foreach (Message message in Messages)
            {
                result = Math.Max(result, message.MessageUid);
            }
            List<Message> collection = messages2.FindAll(delegate(Message m)
            {
                return m.MessageUid > result;
            });
            if ((collection != null) && (collection.Count > 0))
            {
                this._lastMessageUpdateCount = collection.Count;
                foreach (Message message2 in collection)
                {
                    message2._client = this._client;
                    if (processMessages)
                    {
                        message2.Process();
                    }
                }
                this.Messages.AddRange(collection);
                messages.AddRange(collection);
                return messages;
            }
            this._lastMessageUpdateCount = 0;
            return messages;
        }

        public void CopyMessageFromFolder(int messageUID, string srcfolderPath, out Message newMessage)
        {
            newMessage = null;

            int destUID = -1;
            var selectedFolder = _client._selectedFolder;

            _client.SelectFolder(srcfolderPath);

            try
            {
                string command = string.Concat("UID COPY ", messageUID, " \"", FolderPath, "\"\r\n");

                var result = _client.SendAndReceive(command);

                var regex = new Regex(@"\[COPYUID (?<uidvalidity>\d+) \d+ (?<uid>\d+)\]");
                var match = regex.Match(result);
                if (match.Success)
                {
                    var uidvalidity = Convert.ToInt32(match.Groups["uidvalidity"].Value);
                    destUID = Convert.ToInt32(match.Groups["uid"].Value);
                    newMessage = new Message(_client, destUID, this);
                    Messages.Add(newMessage);
                }

            }
            finally
            {
                _client.SelectFolder(selectedFolder);
            }
        }

        public void CopyMessageToFolder(Message msg, Folder folder)
        {
            string folderName = _client._selectedFolder;
            this.Select();
            string command = string.Concat("COPY ", msg.MessageUid, " \"", folder.FolderPath,"\"\r\n");
            _client.SendAndReceive(command);
            
            command = "EXPUNGE\r\n";
            _client.SendAndReceive(command);
            _client.SelectFolder(folderName);
        }

        public void CreateFolder(string name)
        {
            if ((this._client == null) && !this._client._isConnected)
            {
                throw new ImapException("Dont Connect");
            }
            string format = "CREATE \"{0}\"\r\n";
            ArrayList sResultArray = new ArrayList();
            string str2 = string.Format("{0}{1}{2}", this._folderPath, this._client._delimiter, name);
            _client.SendAndReceive(string.Format(format, str2));

            Folder item = new Folder(name);
            item.FolderPath = str2;
            item._client = this._client;
            this._subFolders.Add(item);
            this._subFolders[name].Examine();
        }

        public void DeleteFolder()
        {
            if ((this._client == null) && !this._client._isConnected)
            {
                throw new ImapException("Dont Connect");
            }
            string command = "CLOSE \"" + this._folderPath + "\"\r\n";
            _client.SendAndReceive(command);
            command = "DELETE \"{0}\"\r\n";
            _client.SendAndReceive(string.Format(command, this.FolderPath));
        }

        public void DeleteMessage(Message msg)
        {
            if ((this._client == null) && !this._client._isConnected)
            {
                throw new Exception("Dont Connect");
            }
            if (msg == null)
            {
                throw new ArgumentException("Message is null");
            }
            string folderName = this._client._selectedFolder;
            this._client.SelectFolder(this._folderPath);

            string command = string.Concat("UID STORE ", msg.MessageUid, " +FLAGS (\\Deleted)\r\n");
            this.Select();
            _client.SendAndReceive(command);
            command = "EXPUNGE\r\n";
            _client.SendAndReceive(command);
            //Examine();

            Messages.Remove(msg);

            _client.SelectFolder(folderName);
        }

        public void EmptyFolder()
        {
            if ((this._client == null) && !this._client._isConnected)
            {
                throw new ImapException("Dont Connect");
            }
            string format = "UID STORE {0}:{1} +FLAGS (\\Deleted)\r\n";
            if (this.Messages.Count == 0)
            {
                return;
            }
            int messageUid = this.Messages[0].MessageUid;
            int num2 = this.Messages[this.Messages.Count - 1].MessageUid;
            this.Select();
            _client.SendAndReceive(string.Format(format, messageUid, num2));

            format = "EXPUNGE\r\n";
            _client.SendAndReceive(format);
            this._messages.Clear();
            this.Examine();
        }

        public void Examine()
        {
            ArrayList sResultArray = new ArrayList();
            string command = "EXAMINE \"" + this.FolderPath + "\"\r\n";
            string result = _client.SendAndReceive(command);
            foreach (string str2 in result.Split(new string[] {"\r\n"}, StringSplitOptions.RemoveEmptyEntries))
            {
                if ((!ParseHelper.Exists(str2, ref this._exists) && !ParseHelper.Recent(str2, ref this._recents)) && (!ParseHelper.UidNext(str2, ref this._uidNext) && !ParseHelper.Unseen(str2, ref this._unseen)))
                {
                    ParseHelper.UidValidity(str2, ref this._uidValidity);
                }
            }
        }

        public void GetSubFolders()
        {
            this._subFolders = this._client.GetFolders(this._folderPath);// + this._client._delimiter);
        }

        public void MoveMessageToFolder(Message msg, Folder folder)
        {
            if ((this._client == null) && !this._client._isConnected)
            {
                throw new ImapException("Dont Connect");
            }
            CopyMessageToFolder(msg, folder);
            DeleteMessage(msg);
        }

        //public MessageCollection Search(string path, bool makeProcess)
        //{
        //    if ((this._client == null) && !this._client._isConnected)
        //    {
        //        throw new ImapException("Dont Connect");
        //    }
        //    string folderName = this._client._selectedFolder;
        //    this.Select();
        //    MessageCollection messages = this._client.SearchMessage(path);
        //    foreach (Message message in messages)
        //    {
        //        message._client = this._client;
        //        if (makeProcess)
        //        {
        //            message.Process();
        //        }
        //    }
        //    this._client.SelectFolder(folderName);
        //    return messages;
        //}

        public void Select()
        {
            this._client.SelectFolder(this._folderPath);
        }

        private MessageCollection setMessage()
        {
            this.Select();
            MessageCollection messages = new MessageCollection();
            messages = this._client.SearchMessage("all", this);
            foreach (Message message in messages)
            {
                message._client = this._client;
            }
            return messages;
        }

        private void SubfolderInit()
        {
            foreach (Folder folder in this._subFolders)
            {
                folder._client = this._client;
            }
        }

        public override string ToString()
        {
            return this.Name;
        }

        public int Exists
        {
            get
            {
                return this._exists;
            }
        }

        public string FolderPath
        {
            get
            {
                return this._folderPath;
            }
            set
            {
                this._folderPath = value;
            }
        }

        public bool HasChildren
        {
            get
            {
                return this._hasChildren;
            }
        }

        public bool IsSelectable
        {
            get
            {
                return !_noselect;
            }
        }

        public int LastUpdateMessagesCount
        {
            get
            {
                return this._lastMessageUpdateCount;
            }
        }

        public MessageCollection Messages
        {
            get
            {
                if (this._messages == null)
                {
                    this._messages = this.setMessage();
                }
                return this._messages;
            }
            set
            {
                this._messages = value;
            }
        }

        public string Name
        {
            get
            {
                return this._folderName;
            }
            set
            {
                this._folderName = value;
            }
        }

        public int Recents
        {
            get
            {
                return this._recents;
            }
            set
            {
                this._recents = value;
            }
        }

        public FolderCollection SubFolders
        {
            get
            {
                this.SubfolderInit();
                return this._subFolders;
            }
            set
            {
                this._subFolders = value;
            }
        }

        public int UidNext
        {
            get
            {
                return this._uidNext;
            }
        }

        public string UidValidity
        {
            get
            {
                return this._uidValidity;
            }
        }

        public int Unseen
        {
            get
            {
                return this._unseen;
            }
        }
    }
}

